package com.example.teachingSystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.teachingSystem.mapper.SysMenuMapper;
import com.example.teachingSystem.mapper.SysUserMapper;
import com.example.teachingSystem.mapper.SysUserRoleMapper;
import com.example.teachingSystem.pojo.entity.SysMenu;
import com.example.teachingSystem.pojo.entity.SysUser;
import com.example.teachingSystem.pojo.entity.SysUserRole;
import com.example.teachingSystem.pojo.form.menu.AddMenuForm;
import com.example.teachingSystem.pojo.form.menu.ChangeMenuForm;
import com.example.teachingSystem.pojo.form.menu.MenuPageQuery;
import com.example.teachingSystem.pojo.vo.MenuInfoVo;
import com.example.teachingSystem.pojo.vo.RouteVo;
import com.example.teachingSystem.service.SysMenuService;
import com.example.teachingSystem.service.SysRoleMenuService;
import com.example.teachingSystem.utils.JwtHelper;
import com.example.teachingSystem.utils.result.PageResult;
import com.example.teachingSystem.utils.result.Result;
import com.example.teachingSystem.utils.result.ResultCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author 86147
 * @description 针对表【sys_menu(菜单管理)】的数据库操作Service实现
 * @createDate 2023-12-06 13:56:12
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu>
        implements SysMenuService {
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private JwtHelper jwtHelper;
    @Autowired
    private HttpServletRequest request;

    @Override
    public Result<MenuInfoVo> getMenuById(Long id) {
        SysMenu menu = sysMenuMapper.selectById(id);
        if (menu == null) {
            return Result.build(null, 500, "菜单不存在");
        }
        MenuInfoVo menuInfoVo = new MenuInfoVo();
        BeanUtils.copyProperties(menu, menuInfoVo);
        return Result.ok(menuInfoVo);
    }


    @Override
    public PageResult<MenuInfoVo> getMenuPage(MenuPageQuery menuPageQuery) {
        Page<SysMenu> menuPage = new Page<>(menuPageQuery.getPageNum(), menuPageQuery.getPageSize());
        IPage<MenuInfoVo> menuInfoVoIPage = sysMenuMapper.getMenuPage(menuPage, menuPageQuery);
        menuInfoVoIPage.setRecords(addMenuChildrenToParent(menuInfoVoIPage.getRecords()));
        return PageResult.success(menuInfoVoIPage);
    }


    @Override
    public Result<String> addMenu(AddMenuForm addMenuForm) {
        SysMenu menu = sysMenuMapper.selectOne(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getName, addMenuForm.getName())
                .or().eq(SysMenu::getPath, addMenuForm.getPath()));
        if (menu != null) {
            return Result.build(null, 500, "菜单名称或路径已存在");
        }
        SysMenu sysMenu = new SysMenu();
        BeanUtils.copyProperties(addMenuForm, sysMenu);
        this.save(sysMenu);
        return Result.ok(null, "添加成功");
    }

    @Override
    public Result<String> updateMenu(ChangeMenuForm changeMenuForm) {
        SysMenu menu = sysMenuMapper.selectById(changeMenuForm.getId());
        if (menu == null) {
            return Result.build(null, 500, "菜单不存在");
        }
        SysMenu menu1 = sysMenuMapper.selectOne(new LambdaQueryWrapper<SysMenu>()
                .eq(SysMenu::getName, changeMenuForm.getName())
                .or().eq(SysMenu::getPath, changeMenuForm.getPath()));
        if (!Objects.equals(menu1.getId(), menu.getId())) {
            return Result.build(null, 500, "菜单名称或路径已存在");
        }
        BeanUtils.copyProperties(changeMenuForm, menu);
        this.updateById(menu);
        return Result.ok(null, "修改成功");
    }

    @Override
    public Result<String> deleteMenu(Long id) {
        SysMenu menu = sysMenuMapper.selectById(id);
        if (menu == null) {
            return Result.build(null, 500, "菜单不存在");
        }
        this.removeById(menu);
        new Thread(()->{
            sysRoleMenuService.deleteRoleMenuByMenuId(id);
        }).start();
        return Result.ok(null, "删除成功");
    }

    @Override
    public Result<List<MenuInfoVo>> getMenuOptions() {
        List<MenuInfoVo> menuInfoVos = sysMenuMapper.getMenuOptions();
        return Result.ok(addMenuChildrenToParent(menuInfoVos));
    }

    @Override
    public Result<List<RouteVo>> getRoutes(Long roleId) {
        // 获取请求头中的令牌
        String token = request.getHeader("Authorization");
        Long userId = jwtHelper.getUserId(token);
        SysUser user = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getId, userId));
        if (user == null) {
            return Result.build(null, ResultCodeEnum.USER_ERROR);
        }
        SysUserRole sysUserRole = sysUserRoleMapper.selectOne(new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getUserId, user.getId()).eq(SysUserRole::getRoleId, roleId));
        if (sysUserRole == null) {
            return Result.build(null, 500, "当前用户不存在该角色");
        }
        List<RouteVo> routeVos = sysMenuMapper.getRoutes(roleId);
        List<RouteVo> handleRoutes = addChildrenToParent(routeVos);
        return Result.ok(handleRoutes);
    }

    public List<RouteVo> addChildrenToParent(List<RouteVo> routeVos) {
        List<RouteVo> handleRoutes = new ArrayList<>();

        // Find the top-level routes (parentId = 0)
        for (RouteVo route : routeVos) {
            if (route.getParentId() == 0) {
                handleRoutes.add(route);
            }
        }

        // Add children to their respective parents
        for (RouteVo parent : handleRoutes) {
            addChildren(parent, routeVos);
        }

        return handleRoutes;
    }

    private void addChildren(RouteVo parent, List<RouteVo> routeVos) {
        List<RouteVo> children = new ArrayList<>();

        // Find the children of the parent
        for (RouteVo route : routeVos) {
            if (Objects.equals(route.getParentId(), parent.getId())) {
                children.add(route);
            }
        }

        // Recursively add children to their respective parents
        for (RouteVo child : children) {
            addChildren(child, routeVos);
        }

        // Set the children of the parent
        parent.setChildren(children);
    }

    public List<MenuInfoVo> addMenuChildrenToParent(List<MenuInfoVo> menuInfoVos) {
        List<MenuInfoVo> handleRoutes = new ArrayList<>();

        // Find the top-level routes (parentId = 0)
        for (MenuInfoVo menuInfoVo : menuInfoVos) {
            if (menuInfoVo.getParentId() == 0) {
                handleRoutes.add(menuInfoVo);
            }
        }

        // Add children to their respective parents
        for (MenuInfoVo parent : handleRoutes) {
            addMenuChildren(parent, menuInfoVos);
        }

        return handleRoutes;
    }

    private void addMenuChildren(MenuInfoVo parent, List<MenuInfoVo> menuInfoVos) {
        List<MenuInfoVo> children = new ArrayList<>();

        // Find the children of the parent
        for (MenuInfoVo menuInfoVo : menuInfoVos) {
            if (Objects.equals(menuInfoVo.getParentId(), parent.getId())) {
                children.add(menuInfoVo);
            }
        }

        // Recursively add children to their respective parents
        for (MenuInfoVo child : children) {
            addMenuChildren(child, menuInfoVos);
        }

        // Set the children of the parent
        parent.setChildren(children);
    }
}




